/**
 * @file   Geometry.h
 * @author Wang Heyu <wang@wukong>
 * @date   Wed May  5 10:22:24 2021
 * 
 * @brief A abstract class for all geometry entities,
 * which providing index number and boundary mark.
 * 
 */


#ifndef __CRAZYFISH_GEOMETRY__
#define __CRAZYFISH_GEOMETRY__

#include <valarray>
#include <iostream>

/**
 * An abstract class for geometry entities with index and boundary
 * mark.
 * 
 */
class Geometry
{
public:
    typedef int bm_t;		/**< boundary mark type. */
    
protected:
    size_t index;		/**< index number. -1 means not assigned.*/
    bm_t boundary_mark;		/**< boundary mark value. default is 0, means an inner entity.*/
    // size_t n_dofs;  unused
    std::valarray<size_t> vertex;
    std::valarray<size_t> boundary;
    std::valarray<int> neighbor;
    std::valarray<size_t> dofs;

public:
    /** 
     * Interface to get the index number.
     * 
     * 
     * @return index number.
     */
    virtual size_t get_index() const;

    /** 
     * Interface to get the boundary mark value.
     * 
     * 
     * @return boundary mark value.
     */
    virtual bm_t get_boundary_mark() const;

    /** 
     * Interface to set the index number.
     * 
     * @param _idx index number. 
     */
    virtual void set_index(size_t _idx);

    /** 
     * Interface to set the boundary mark value.
     * 
     * @param _bm boundary mark value. 
     */
    virtual void set_boundary_mark(bm_t _bm);

    virtual size_t get_n_vertex() const;

    virtual size_t get_n_boundary() const;

    virtual size_t get_n_neighbor() const;

    virtual size_t get_n_dofs() const;
    
    virtual void set_n_dofs(size_t _n);

    virtual void set_n_vertex(size_t _n);

    virtual void set_n_boundary(size_t _n);

    virtual void set_n_neighbor(size_t _n);

    virtual size_t get_vertex(size_t _i) const;

    virtual size_t get_boundary(size_t _i) const;

    virtual int get_neighbor(size_t _i) const;

    virtual size_t get_dof(size_t _i) const;

    virtual const std::valarray<size_t> &get_dof() const;

    virtual void set_vertex(size_t _i, size_t _ivtx);

    virtual void set_boundary(size_t _i, size_t _ibnd);

    virtual void set_neighbor(size_t _i, int _inei);

    virtual void set_dof(size_t _i, size_t _idof);

    /** 
     * Default constuctor.
     * 
     */
    Geometry();
};

Geometry::Geometry()
{
    index = -1;   /// means no number.
    boundary_mark = 0;  /// the default is an inner entity.
};

size_t Geometry::get_index() const
{
    return index;
};

Geometry::bm_t Geometry::get_boundary_mark() const
{
    return boundary_mark;
};

void Geometry::set_index(size_t _idx) 
{
    index = _idx;
};

void Geometry::set_boundary_mark(bm_t _bm)
{
    boundary_mark = _bm;
};

size_t Geometry::get_n_vertex() const
{
    return vertex.size();
};

size_t Geometry::get_n_boundary() const
{
    return boundary.size();
};

size_t Geometry::get_n_neighbor() const
{
    return neighbor.size();
};

size_t Geometry::get_n_dofs() const
{
    return dofs.size();
};


void Geometry::set_n_dofs(size_t _n)
{
    dofs.resize(_n);
};

void Geometry::set_n_vertex(size_t _n)
{
    vertex.resize(_n);
};

void Geometry::set_n_boundary(size_t _n)
{
    boundary.resize(_n);
};

void Geometry::set_n_neighbor(size_t _n)
{
    neighbor.resize(_n);
};


size_t Geometry::get_vertex(size_t _i) const
{
    return vertex[_i];
};

size_t Geometry::get_boundary(size_t _i) const
{
    return boundary[_i];
};

int Geometry::get_neighbor(size_t _i) const
{
    return neighbor[_i];
};

size_t Geometry::get_dof(size_t _i) const
{
    return dofs[_i];
};

const std::valarray<size_t> &Geometry::get_dof() const
{
    return dofs;
};

void Geometry::set_vertex(size_t _i, size_t _ivtx)
{
    vertex[_i] = _ivtx;
};

void Geometry::set_boundary(size_t _i, size_t _ibnd)
{
    boundary[_i] = _ibnd;
};

void Geometry::set_neighbor(size_t _i, int _inei)
{
    neighbor[_i] = _inei;
};

void Geometry::set_dof(size_t _i, size_t _idof)
{
    dofs[_i] = _idof;
};

#else
// DO NOTHING.
#endif
